home *** CD-ROM | disk | FTP | other *** search
/ Internet Info 1994 March / Internet Info CD-ROM (Walnut Creek) (March 1994).iso / networking / ip / ka9q / net_src.arc / slip.c < prev    next >
Encoding:
C/C++ Source or Header  |  1989-05-09  |  8.2 KB  |  400 lines

  1. /* Send and receive IP datagrams on serial lines. Compatible with SLIP
  2.  * under Berkeley Unix.
  3.  */
  4. #include <stdio.h>
  5. #include "config.h"
  6. #include "global.h"
  7. #include "mbuf.h"
  8. #include "iface.h"
  9. #include "ax25.h"
  10. #include "slip.h"
  11. #include "asy.h"
  12. #include "trace.h"
  13. #if defined(MODEM_CALL)
  14. #include <string.h>
  15. #include "timer.h"
  16. #endif
  17.  
  18. extern unsigned restricted_dev;
  19. int asy_ioctl();
  20. int kiss_ioctl();
  21. int slip_send();
  22. void doslip();
  23. int asy_output();
  24.  
  25. /* Slip level control structure */
  26. struct slip slip[ASY_MAX];
  27.  
  28. /* Send routine for point-to-point slip
  29.  * This is a trivial function since there is no slip link-level header
  30.  */
  31. int
  32. slip_send(data,interface,gateway,precedence,delay,throughput,reliability)
  33. struct mbuf *data;        /* Buffer to send */
  34. struct interface *interface;    /* Pointer to interface control block */
  35. int32 gateway;            /* Ignored (SLIP is point-to-point) */
  36. char precedence;
  37. char delay;
  38. char throughput;
  39. char reliability;
  40. {
  41.     if(interface == NULLIF){
  42.         free_p(data);
  43.         return -1;
  44.     }
  45.     dump(interface,IF_TRACE_OUT,TRACE_IP,data);
  46.     return (*interface->raw)(interface,data);
  47. }
  48. /* Send a raw slip frame -- also trivial */
  49. int
  50. slip_raw(interface,data)
  51. struct interface *interface;
  52. struct mbuf *data;
  53. {
  54.     /* Queue a frame on the slip output queue and start transmitter */
  55.     return slipq(interface->dev,data);
  56. }
  57. /* Encode a raw packet in slip framing, put on link output queue, and kick
  58.  * transmitter
  59.  */
  60. static int
  61. slipq(dev,data)
  62. int16 dev;        /* Serial line number */
  63. struct mbuf *data;    /* Buffer to be sent */
  64. {
  65.     register struct slip *sp;
  66.     struct mbuf *slip_encode(),*bp;
  67.     void asy_start();
  68.  
  69.     if((bp = slip_encode(data)) == NULLBUF)
  70.         return -1;    
  71.  
  72.     sp = &slip[dev];
  73.     enqueue(&sp->sndq,bp);
  74.     sp->sndcnt++;
  75.     if(sp->tbp == NULLBUF)
  76.         asy_start(dev);
  77.     return 0;
  78. }
  79. /* Start output, if possible, on asynch device dev */
  80. static void
  81. asy_start(dev)
  82. int16 dev;
  83. {
  84.     register struct slip *sp;
  85.  
  86.     if(!stxrdy(dev))
  87.         return;        /* Transmitter not ready */
  88.  
  89.     sp = &slip[dev];
  90.     if(sp->tbp != NULLBUF){
  91.         /* transmission just completed */
  92.         free_p(sp->tbp);
  93.         sp->tbp = NULLBUF;
  94.     }
  95.     if(sp->sndq == NULLBUF)
  96.         return;    /* No work */
  97.  
  98.     sp->tbp = dequeue(&sp->sndq);
  99.     sp->sndcnt--;
  100.     asy_output(dev,sp->tbp->data,sp->tbp->cnt);
  101. }
  102. /* Encode a packet in SLIP format */
  103. static
  104. struct mbuf *
  105. slip_encode(bp)
  106. struct mbuf *bp;
  107. {
  108.     struct mbuf *lbp;    /* Mbuf containing line-ready packet */
  109.     register char *cp;
  110.     char c;
  111.  
  112.     /* Allocate output mbuf that's twice as long as the packet.
  113.      * This is a worst-case guess (consider a packet full of FR_ENDs!)
  114.      */
  115.     lbp = alloc_mbuf(2*len_mbuf(bp) + 2);
  116.     if(lbp == NULLBUF){
  117.         /* No space; drop */
  118.         free_p(bp);
  119.         return NULLBUF;
  120.     }
  121.     cp = lbp->data;
  122.  
  123.     /* Flush out any line garbage */
  124.     *cp++ = FR_END;
  125.  
  126.     /* Copy input to output, escaping special characters */
  127.     while(pullup(&bp,&c,1) == 1){
  128.         switch(uchar(c)){
  129.         case FR_ESC:
  130.             *cp++ = FR_ESC;
  131.             *cp++ = T_FR_ESC;
  132.             break;
  133.         case FR_END:
  134.             *cp++ = FR_ESC;
  135.             *cp++ = T_FR_END;
  136.             break;
  137.         default:
  138.             *cp++ = c;
  139.         }
  140.     }
  141.     *cp++ = FR_END;
  142.     lbp->cnt = cp - lbp->data;
  143.     return lbp;
  144. }
  145. /* Process incoming bytes in SLIP format
  146.  * When a buffer is complete, return it; otherwise NULLBUF
  147.  */
  148. static
  149. struct mbuf *
  150. slip_decode(dev,c)
  151. int16 dev;    /* Slip unit number */
  152. char c;        /* Incoming character */
  153. {
  154.     struct mbuf *bp;
  155.     register struct slip *sp;
  156.  
  157.     sp = &slip[dev];
  158.     switch(uchar(c)){
  159.     case FR_END:
  160.         bp = sp->rbp;
  161.         sp->rbp = NULLBUF;
  162.         sp->rcnt = 0;
  163.         return bp;    /* Will be NULLBUF if empty frame */
  164.     case FR_ESC:
  165.         sp->escaped = 1;
  166.         return NULLBUF;
  167.     }
  168.     if(sp->escaped){
  169.         /* Translate 2-char escape sequence back to original char */
  170.         sp->escaped = 0;
  171.         switch(uchar(c)){
  172.         case T_FR_ESC:
  173.             c = FR_ESC;
  174.             break;
  175.         case T_FR_END:
  176.             c = FR_END;
  177.             break;
  178.         default:
  179.             sp->errors++;
  180.             break;
  181.         }
  182.     }
  183.     /* We reach here with a character for the buffer;
  184.      * make sure there's space for it
  185.      */
  186.     if(sp->rbp == NULLBUF){
  187.         /* Allocate first mbuf for new packet */
  188.         if((sp->rbp1 = sp->rbp = alloc_mbuf(SLIP_ALLOC)) == NULLBUF)
  189.             return NULLBUF; /* No memory, drop */
  190.         sp->rcp = sp->rbp->data;
  191.     } else if(sp->rbp1->cnt == SLIP_ALLOC){
  192.         /* Current mbuf is full; link in another */
  193.         if((sp->rbp1->next = alloc_mbuf(SLIP_ALLOC)) == NULLBUF){
  194.             /* No memory, drop whole thing */
  195.             free_p(sp->rbp);
  196.             sp->rbp = NULLBUF;
  197.             sp->rcnt = 0;
  198.             return NULLBUF;
  199.         }
  200.         sp->rbp1 = sp->rbp1->next;
  201.         sp->rcp = sp->rbp1->data;
  202.     }
  203.     /* Store the character, increment fragment and total
  204.      * byte counts
  205.      */
  206.     *sp->rcp++ = c;
  207.     sp->rbp1->cnt++;
  208.     sp->rcnt++;
  209.     return NULLBUF;
  210. }
  211. /* Process SLIP line I/O */
  212. void
  213. doslip(interface)
  214. struct interface *interface;
  215. {
  216.     char c;
  217.     struct mbuf *bp;
  218.     int16 dev;
  219.     int16 asy_recv();
  220.  
  221.     dev = interface->dev;
  222.     if(dev == restricted_dev) return;
  223.     /* Process any pending input */
  224.     while(asy_recv(dev,&c,1) != 0)
  225.         if((bp = slip_decode(dev,c)) != NULLBUF)
  226.             (*slip[dev].recv)(interface,bp);
  227.  
  228.     /* Kick the transmitter if it's idle */
  229.     if(stxrdy(dev))
  230.         asy_start(dev);
  231. }
  232. /* Unwrap incoming SLIP packets -- trivial operation since there's no
  233.  * link level header
  234.  */
  235. void
  236. slip_recv(interface,bp)
  237. struct interface *interface;
  238. struct mbuf *bp;
  239. {
  240.     int ip_route();
  241.  
  242.     /* By definition, all incoming packets are "addressed" to us */
  243.     dump(interface,IF_TRACE_IN,TRACE_IP,bp);
  244.     ip_route(bp,0);
  245. }
  246.  
  247. #if defined(MODEM_CALL)
  248.  
  249. int check_time(),keep_things_going();
  250.  
  251. static char *ex="r\015t\011s n\012E\004b\010\\\\N\000";
  252. static struct timer ar;
  253. static int debug;
  254.  
  255. static
  256. int m_send(dev, a)
  257. unsigned dev;
  258. char *a;
  259. {
  260.     int i;
  261.     unsigned l;
  262.     char *ss, *cp, *pt;
  263.  
  264.     ss=pt=a;
  265.     l=0;
  266.     while(*a) {
  267.         if(*a=='\\') {
  268.             a++;
  269.             if(*a=='d') {
  270.                 asy_output(dev,ss,l);
  271.                 l=0;
  272.                 a++;
  273.                 ss=pt=a;
  274.                 set_timer(&ar,1000);
  275.                 start_timer(&ar);
  276.                     while(ar.state == TIMER_RUN)
  277.                     keep_things_going();
  278.                 continue;
  279.             }
  280.             if((cp = strchr(ex,*a)) != NULL) {
  281.                 *pt++ = *(cp+1);
  282.                 l++;
  283.                 a++;
  284.                 continue;
  285.             }
  286.         } /* if(*a=='\\') */
  287.         *pt++ = *a++;
  288.         l++;
  289.     }
  290.     asy_output(dev,ss,l);
  291. } /* m_send */
  292.  
  293. /******************************************************************************
  294.  * returns the character position of the substring pat within the string
  295.  *  src if the substring exists, 0 if the substring does not exist.
  296.  *  the first character position is considered to be 1, not 0 which
  297.  *  is the first position within the array.
  298.  */
  299. static
  300. int xinstr(src,pat)
  301. char *src,*pat;
  302. {
  303.     register char *s_src, *s_pat;
  304.     int rtn;
  305.  
  306.     s_src=src;
  307.     s_pat=pat;
  308.     rtn=1;
  309.     while(*s_src) {
  310.         while((*s_pat) && (*s_src==*s_pat)) { s_src++; s_pat++; }
  311.         if(!(*s_pat)) return(rtn);
  312.         rtn++; s_pat=pat; s_src=(++src);
  313.     }
  314.     return(0);
  315. } /* xinstr */
  316.  
  317. static
  318. int m_expect(dev, a)
  319. unsigned dev;
  320. char *a;
  321. {
  322.     char *str, *pstr, c;
  323.     int tot;
  324.  
  325.     if(*a=='\\') return 1;
  326. /*
  327.  * make room for the received string
  328.  */
  329.         if((str=malloc(5000)) == NULL) {
  330.         printf("No room for malloc: m_expect\n");
  331.         fflush(stdout);
  332.         return -1;
  333.     }
  334. /*
  335.  * a single backspace means don't wait for anything
  336.  */
  337.     pstr=str;
  338.     *pstr='\0';
  339.     tot=0;
  340.     set_timer(&ar,30000);
  341.     start_timer(&ar);
  342.     while (!xinstr(str,a)) {
  343.         while(asy_recv(dev,&c,1)) { 
  344. /*
  345.  * ignore incoming nulls
  346.  */
  347.             if(c) {
  348.                 *(pstr++)=c;
  349.                 *pstr='\0';
  350.                 if(++tot > 4995) {
  351.                     if(debug) printf("%s",str);fflush(stdout);
  352.                     free(str);
  353.                     return -1;
  354.                 }
  355.             }
  356.         }
  357.         check_time();
  358.         if(ar.state != TIMER_RUN) {
  359.             free(str);
  360.             if(debug) printf("%s",str);fflush(stdout);
  361.             return -1;
  362.         }
  363.     }
  364.     if(debug) printf("%s",str);fflush(stdout);
  365.     free(str);
  366.     return 1;
  367. } /* m_expect */
  368.  
  369. int modem_init(dev, argc, argv)
  370. unsigned dev;
  371. int argc;
  372. char **argv;
  373. {
  374.     int i, done;
  375.     i=0;
  376.     debug = 0;
  377.     if(argv[0][0]=='-') {
  378.         debug=1;
  379.         i++;
  380.         argc--;
  381.     }
  382.     while(argc) {
  383.         if(debug) {
  384.             printf("\nI'm sending  : '%s'\n",argv[i]);
  385.             fflush(stdout);
  386.         }
  387.         if(debug && argc>1) {
  388.             printf("I'm expecting: '%s'\n",argv[1+i]);
  389.             fflush(stdout);
  390.         }
  391.         if(m_send(dev,argv[i++]) == -1) return -1;
  392.         if(--argc>0) {
  393.             if(m_expect(dev,argv[i++]) == -1) return -1;
  394.             argc--;
  395.         }
  396.     }
  397.     return 1;
  398. } /* modem_init */
  399. #endif /* MODEM_CALL */
  400.